﻿using Common.Contract.Authentication.Record;
using Common.Contract.Customer.Record;
using Common.Contract.Customer.Request;
using Common.Contract.Customer.Response;
using Common.Contract.Paging;
using Common.Contract.SystemConfig.Record;
using Common.Service.Command;
using Customer.Model.Interface;
using Customer.Model.Model;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace Customer.Core.ServiceCommand
{
    public class RetrieveCustomerServiceCommand : ProviderServiceCommand<IProviderFactory, RetrieveCustomerRequest, RetrieveCustomerResponse>
    {
        #region Properties
        public UserRecord Dao;
        public int pageSize = 10, pageIndex = 0, totalRecord = 0;
        public DateTime? FromDate;
        private List<CustomerRegion> ListCustomer = new List<CustomerRegion>();
        public FilterRecord SearchColumns;
        Dictionary<string, BranchRecord> ListBranches;
        CultureInfo cul = CultureInfo.GetCultureInfo("vi-VN");   // try with "en-US"
        #endregion
        public RetrieveCustomerServiceCommand(IProviderFactory providers) : base(providers) { }
        protected override void Validate(RetrieveCustomerRequest request)
        {
            if (request == null) throw new ArgumentNullException("request");
            if (!request.Header.ApplicationKey.HasValue || request.Header.ApplicationKey == Guid.Empty)
            {
                throw new ArgumentException("ApplicationKey must be set", "request");
            }
            if (request.CurrentUser == null)
            {
                throw new ArgumentException("MSBO Dao must be set", "request");
            }
            else
            {
                Dao = Request.CurrentUser;
            }
            if (string.IsNullOrEmpty(request.Type))
            {
                throw new ArgumentException("Type of customer must be set", "request");
            }
            if (Request.Page != null)
            {
                pageIndex = Request.Page.PageIndex ?? 0;
                pageSize = Request.Page.PageSize ?? 0;
            }
            if (request.FromDate.HasValue)
            {
                FromDate = Request.FromDate;
            }
            SearchColumns = Request.Filter;
        }

        protected override bool OnExecute(RetrieveCustomerResponse response)
        {
            bool isSuccess = true;
            string errorMessage = string.Empty;
            try
            {
                Dictionary<string, BranchRecord> listBranches = Providers.Branchs.RetrieveAllBranches().Select(x => new BranchRecord
                {
                    BranchId = x.BranchId,
                    BranchName = x.BranchNameSme,
                    Region = x.Region
                }).ToList().ToDictionary(x => x.BranchId);
                List<CustomerRecord> records = new List<CustomerRecord>();

                switch (Request.Type)
                {
                    case "deposit":
                        records = GetCustomerDeposit();
                        break;
                    case "new_deposit":
                        records = GetCustomerDeposit(true);
                        break;
                    case "loan":
                        records = GetCustomerLoan();
                        break;
                    case "new_loan":
                        records = GetCustomerLoan(true);
                        break;
                    case "card":
                        records = GetCustomerCard();
                        break;
                    case "new_card":
                        records = GetCustomerCard(true);
                        break;
                    case "i2b":
                        records = GetCustomerI2b();
                        break;
                    case "new_i2b":
                        records = GetCustomerI2b(true);
                        break;
                    case "pos":
                        records = GetCustomerPos();
                        break;
                    case "new_pos":
                        records = GetCustomerPos(true);
                        break;
                    case "trade":
                        records = GetCustomerTrade();
                        break;
                    case "new_trade":
                        records = GetCustomerTrade(true);
                        break;
                    case "chuoi":
                        records = GetCustomerChuoi();
                        break;
                    case "new_chuoi":
                        records = GetCustomerChuoi(true);
                        break;
                    default:
                        break;
                }
                response.Records = records;
                response.Page = new PageRecord
                {
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    TotalRecords = totalRecord
                };
            }
            catch (Exception e)
            {
                isSuccess = false;
                errorMessage = e.Message;

            }

            response.ErrorMessage = errorMessage;
            return isSuccess;
        }

        #region Helper Methods
        private List<CustomerRecord> GetCustomerDeposit(bool isNew = false)
        {
            List<CustomerRecord> result = new List<CustomerRecord>();
            string group = string.Empty, grouptype = string.Empty;
            List<string> listFilter = new List<string>();
            if (!string.IsNullOrEmpty(Request.Group) && !string.IsNullOrEmpty(Request.GroupType))
            {
                group = Request.Group;
                grouptype = Request.GroupType;
                listFilter = grouptype.Split(',').ToList();
            }
            if (isNew)
            {
                ListCustomer = Providers.Customers.RetrieveCustomerDepositByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, FromDate, group: group, grouptype: grouptype);
            }
            else
            {
                ListCustomer = Providers.Customers.RetrieveCustomerDepositByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, group: group, grouptype: grouptype);
            }

            if (ListCustomer != null && ListCustomer.Count > 0)
            {
                result = ListCustomer.Select(x => new CustomerRecord
                {
                    DaoName = x.DaoName,
                    Dao = x.Dao,
                    Branch = ListBranches.ContainsKey(x.BranchId) ? ListBranches[x.BranchId]:new BranchRecord(),
                    CIF = x.Cif,
                    Name = x.CusName,
                    Address = x.Address,
                    VpbIndustry = Request.Lang.Equals("vi") ? x.IndustryName : x.IndustryNameEn,
                    DateOpenCif = x.CusOpenDate.HasValue ? x.CusOpenDate.Value : DateTime.MinValue,
                    Balance = (!string.IsNullOrEmpty(group) && !string.IsNullOrEmpty(grouptype)) ? (group.Equals("0") ? x.Deposits.Where(z => listFilter.Contains(z.ProductName)).Sum(y => y.BalQd).ToString("#,###", cul.NumberFormat) : x.Deposits.Where(z => listFilter.Contains(z.ChuongTrinhSp)).Sum(y => y.BalQd).ToString("#,###", cul.NumberFormat)) : x.Deposits.Sum(y => y.BalQd).ToString("#,###", cul.NumberFormat)
                }).ToList();
            }
            return result;
        }

        private List<CustomerRecord> GetCustomerLoan(bool isNew = false)
        {
            List<CustomerRecord> result = new List<CustomerRecord>();
            string group = string.Empty, grouptype = string.Empty;
            List<string> listFilter = new List<string>();
            if (!string.IsNullOrEmpty(Request.Group) && !string.IsNullOrEmpty(Request.GroupType))
            {
                group = Request.Group;
                grouptype = Request.GroupType;
                listFilter = grouptype.Split(',').ToList();
            }
            if (isNew)
            {
                //ListCustomer = Providers.Customers.RetrieveCustomerNewLoanByDao(out totalRecord, Dao, SearchIndex, TextSearch, Request.Lang, pageSize, pageIndex, group: group, grouptype: grouptype);
            }
            else
            {
                ListCustomer = Providers.Customers.RetrieveCustomerLoanByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, group: group, grouptype: grouptype);
            }

            if (ListCustomer != null && ListCustomer.Count > 0)
            {
                result = ListCustomer.Select(x => new CustomerRecord
                {
                    DaoName = x.DaoName,
                    Dao = x.Dao,
                    Branch = ListBranches.ContainsKey(x.BranchId) ? ListBranches[x.BranchId]:new BranchRecord(),
                    CIF = x.Cif,
                    Name = x.CusName,
                    Address = x.Address,
                    VpbIndustry = Request.Lang.Equals("vi") ? x.IndustryName : x.IndustryNameEn,
                    DateOpenCif = x.CusOpenDate.HasValue ? x.CusOpenDate.Value : DateTime.MinValue,
                    Balance = isNew == true ? x.NewLendings.FirstOrDefault().BalQd.ToString("#,###", cul.NumberFormat) : (!string.IsNullOrEmpty(group) && !string.IsNullOrEmpty(grouptype)) ? (group.Equals("0") ? x.Loans.Where(z => listFilter.Contains(z.CtUudaiVay)).Sum(y => y.BalQd).ToString("#,###", cul.NumberFormat) : (group.Equals("1") ? x.Loans.Where(z => listFilter.Contains(z.ChuongTrinhSp)).Sum(y => y.BalQd).ToString("#,###", cul.NumberFormat) : x.Loans.Where(z => listFilter.Contains(z.NhomSpLoan)).Sum(y => y.BalQd).ToString("#,###", cul.NumberFormat))) : x.Loans.Sum(y => y.BalQd).ToString("#,###", cul.NumberFormat),
                    NhomNo = isNew == true ? "0" : x.Loans.FirstOrDefault().NhomNo
                }).ToList();
            }
            return result;
        }
        private List<CustomerRecord> GetCustomerCard(bool isNew = false)
        {
            List<CustomerRecord> result = new List<CustomerRecord>();
            if (isNew)
            {
                ListCustomer = Providers.Customers.RetrieveCustomerCardByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, FromDate);
            }
            else
            {
                ListCustomer = Providers.Customers.RetrieveCustomerCardByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex);
            }

            if (ListCustomer != null && ListCustomer.Count > 0)
            {
                result = ListCustomer.Select(x => new CustomerRecord
                {
                    DaoName = x.DaoName == null ? string.Empty : x.DaoName,
                    Dao = x.Dao,
                    Branch = ListBranches.ContainsKey(x.BranchId) ? ListBranches[x.BranchId]:new BranchRecord(),
                    CIF = x.Cif,
                    Name = x.CusName,
                    Address = x.Address,
                    VpbIndustry = Request.Lang.Equals("vi") ? x.IndustryName : x.IndustryNameEn,
                    DateOpenCif = x.CusOpenDate.HasValue ? x.CusOpenDate.Value : DateTime.MinValue,
                    NoOfCard = x.Cards.FirstOrDefault().NoOfCard,
                    ScoredCard = x.Cards.FirstOrDefault().ScoredCard,
                    Balance = x.Cards.FirstOrDefault().Balance.ToString("##,##0.00")
                }).ToList();
            }
            return result;
        }
        private List<CustomerRecord> GetCustomerI2b(bool isNew = false)
        {
            List<CustomerRecord> result = new List<CustomerRecord>();
            List<ProductI2B> listCustI2B = new List<ProductI2B>();
            if (isNew)
            {
                listCustI2B = Providers.Customers.RetrieveCustomerI2bByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, FromDate);
            }
            else
            {
                listCustI2B = Providers.Customers.RetrieveCustomerI2bByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex);
            }

            if (listCustI2B != null && listCustI2B.Count > 0)
            {
                result = listCustI2B.Select(x => new CustomerRecord
                {
                    DaoName = x.DaoName,
                    Dao = x.Dao,
                    Branch = ListBranches.ContainsKey(x.BranchId) ? ListBranches[x.BranchId] : new BranchRecord(),
                    CIF = x.Cif,
                    Name = x.CusName,
                    VpbIndustry = Request.Lang.Equals("vi") ? x.IndustryName : x.IndustryNameEn,
                    DateOpenCif = x.CusOpenDate.HasValue ? x.CusOpenDate.Value : DateTime.MinValue,
                    NoUser = x.NoUser.ToString() + " (" + x.NoUserActive.ToString() + ")",
                    NoUserActived = x.NoUserActive.ToString(),
                }).ToList();
            }
            return result;
        }

        private List<CustomerRecord> GetCustomerPos(bool isNew = false)
        {
            List<CustomerRecord> result = new List<CustomerRecord>();
            if (isNew)
            {
                ListCustomer = Providers.Customers.RetrieveCustomerPosByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, FromDate);
            }
            else
            {
                ListCustomer = Providers.Customers.RetrieveCustomerPosByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex);
            }

            if (ListCustomer != null && ListCustomer.Count > 0)
            {
                result = ListCustomer.Select(x => new CustomerRecord
                {
                    DaoName = x.DaoName,
                    Dao = x.Dao,
                    Branch = ListBranches.ContainsKey(x.BranchId) ? ListBranches[x.BranchId] : new BranchRecord(),
                    CIF = x.Cif,
                    Name = x.CusName,
                    VpbIndustry = Request.Lang.Equals("vi") ? x.IndustryName : x.IndustryNameEn,
                    DateOpenCif = x.CusOpenDate.HasValue ? x.CusOpenDate.Value : DateTime.MinValue,
                    NoPos = x.Poss.FirstOrDefault().CountTk.ToString(),
                    TransactionInMonth = x.Poss.FirstOrDefault().GiaoDichInMonth.ToString("#,###", cul.NumberFormat)
                }).ToList();
            }
            return result;
        }

        private List<CustomerRecord> GetCustomerTrade(bool isNew = false)
        {
            List<CustomerRecord> result = new List<CustomerRecord>();
            var listCustTrade = new List<ProductTrade>();
            if (isNew)
            {
                listCustTrade = Providers.Customers.RetrieveCustomerTradeByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, FromDate);
            }
            else
            {
                listCustTrade = Providers.Customers.RetrieveCustomerTradeByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex);
            }

            if (listCustTrade != null && listCustTrade.Count > 0)
            {
                result = listCustTrade.Select(x => new CustomerRecord
                {
                    DaoName = x.DaoName,
                    Dao = x.Dao,
                    Branch = ListBranches.ContainsKey(x.BranchId) ? ListBranches[x.BranchId] : new BranchRecord(),
                    CIF = x.Cif,
                    Name = x.CustName,
                    VpbIndustry = Request.Lang.Equals("vi") ? x.IndustryName : x.IndustryNameEn,
                    DateOpenCif = x.CusOpenDate.HasValue ? x.CusOpenDate.Value : DateTime.MinValue,
                    BalTtqt = x.BalTtqt.ToString("#,###", cul.NumberFormat),
                    BalBl = x.BalBl.ToString("#,###", cul.NumberFormat),
                    DuNoTradeLoan = x.DuNoTradeLoan.ToString("#,###", cul.NumberFormat),
                    Chuoi = x.Chuoi
                }).ToList();
            }
            return result;
        }

        private List<CustomerRecord> GetCustomerChuoi(bool isNew = false)
        {
            List<CustomerRecord> result = new List<CustomerRecord>();
            var listCustChuoi = new List<ProductChuoi>();
            if (isNew)
            {
                listCustChuoi = Providers.Customers.RetrieveCustomerChuoiByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex, FromDate);
            }
            else
            {
                listCustChuoi = Providers.Customers.RetrieveCustomerChuoiByDao(out totalRecord, Dao, SearchColumns, Request.Lang, pageSize, pageIndex);
            }

            if (listCustChuoi != null && listCustChuoi.Count > 0)
            {
                result = listCustChuoi.Select(x => new CustomerRecord
                {
                    DaoName = x.DaoName,
                    Dao = x.Dao,
                    Branch = ListBranches.ContainsKey(x.BranchId) ? ListBranches[x.BranchId] : new BranchRecord(),
                    CIF = x.CustId,
                    Name = x.CusName,
                    VpbIndustry = Request.Lang.Equals("vi") ? x.IndustryName : x.IndustryNameEn,
                    DateOpenCif = x.CusOpenDate.HasValue ? x.CusOpenDate.Value : DateTime.MinValue,
                    Chuoi = x.FundProgram
                }).ToList();
            }
            return result;
        }

        #endregion
    }
}
